package com.itjin.health.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.itjin.health.domain.dto.rehabilitation.RehabilitationPlanAddRequest;
import com.itjin.health.domain.dto.rehabilitation.RehabilitationPlanProgressUpdateRequest;
import com.itjin.health.domain.dto.rehabilitation.RehabilitationPlanUpdateRequest;
import com.itjin.health.domain.entity.InjuryReport;
import com.itjin.health.domain.entity.OfflineAssessmentAppointment;
import com.itjin.health.domain.entity.OnlineAssessmentAppointment;
import com.itjin.health.domain.entity.RehabilitationPlan;
import com.itjin.health.domain.entity.User;
import com.itjin.health.domain.vo.RehabilitationPlanDetailVO;
import com.itjin.health.domain.vo.RehabilitationPlanVO;
import com.itjin.health.exception.BusinessException;
import com.itjin.health.exception.ErrorCode;
import com.itjin.health.mapper.InjuryReportMapper;
import com.itjin.health.mapper.OfflineAssessmentAppointmentMapper;
import com.itjin.health.mapper.OnlineAssessmentAppointmentMapper;
import com.itjin.health.mapper.RehabilitationPlanMapper;
import com.itjin.health.mapper.UserMapper;
import com.itjin.health.service.RehabilitationPlanService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
@Slf4j
public class RehabilitationPlanServiceImpl extends ServiceImpl<RehabilitationPlanMapper, RehabilitationPlan>
    implements RehabilitationPlanService {

  @Resource
  private UserMapper userMapper;

  @Resource
  private InjuryReportMapper injuryReportMapper;

  @Resource
  private OnlineAssessmentAppointmentMapper onlineAssessmentAppointmentMapper;

  @Resource
  private OfflineAssessmentAppointmentMapper offlineAssessmentAppointmentMapper;

  // 状态名称映射
  private static final Map<Integer, String> STATUS_MAP = new HashMap<Integer, String>() {
    {
      put(0, "草稿");
      put(1, "进行中");
      put(2, "已完成");
      put(3, "已取消");
    }
  };

  // 进度状态名称映射
  private static final Map<Integer, String> PROGRESS_STATUS_MAP = new HashMap<Integer, String>() {
    {
      put(0, "未开始");
      put(1, "进行中");
      put(2, "已完成");
    }
  };

  @Override
  public Integer addRehabilitationPlan(RehabilitationPlanAddRequest rehabilitationPlanAddRequest, Integer therapistId) {
    if (rehabilitationPlanAddRequest == null) {
      throw new BusinessException(ErrorCode.PARAMS_ERROR);
    }

    // 检查理疗师是否存在
    User therapist = userMapper.selectById(therapistId);
    if (therapist == null) {
      throw new BusinessException(ErrorCode.PARAMS_ERROR, "理疗师不存在");
    }

    // 检查患者是否存在
    User patient = userMapper.selectById(rehabilitationPlanAddRequest.getPatientId());
    if (patient == null) {
      throw new BusinessException(ErrorCode.PARAMS_ERROR, "患者不存在");
    }

    // 如果关联了伤病报告，检查伤病报告是否存在
    Integer injuryReportId = rehabilitationPlanAddRequest.getInjuryReportId();
    InjuryReport injuryReport = null;
    if (injuryReportId != null) {
      injuryReport = injuryReportMapper.selectById(injuryReportId);
      if (injuryReport == null) {
        throw new BusinessException(ErrorCode.PARAMS_ERROR, "伤病报告不存在");
      }
    }

    // 校验必要参数
    String title = rehabilitationPlanAddRequest.getTitle();
    if (title == null || title.isEmpty()) {
      throw new BusinessException(ErrorCode.PARAMS_ERROR, "标题不能为空");
    }

    if (rehabilitationPlanAddRequest.getStartDate() == null) {
      throw new BusinessException(ErrorCode.PARAMS_ERROR, "开始日期不能为空");
    }

    if (rehabilitationPlanAddRequest.getEndDate() == null) {
      throw new BusinessException(ErrorCode.PARAMS_ERROR, "结束日期不能为空");
    }

    // 创建康复计划实体
    RehabilitationPlan rehabilitationPlan = new RehabilitationPlan();
    BeanUtil.copyProperties(rehabilitationPlanAddRequest, rehabilitationPlan);

    // 设置理疗师ID和初始进度状态
    rehabilitationPlan.setTherapistId(therapistId);
    rehabilitationPlan.setProgressStatus(0);

    // 根据开始日期和结束日期自动设置status状态
    LocalDateTime now = LocalDateTime.now();
    LocalDateTime startDateTime = rehabilitationPlanAddRequest.getStartDate().atStartOfDay();
    LocalDateTime endDateTime = rehabilitationPlanAddRequest.getEndDate().atTime(23, 59, 59);

    if (now.isBefore(startDateTime)) {
      // 当前时间在开始日期之前，设置为草稿状态
      rehabilitationPlan.setStatus(0);
    } else if (now.isAfter(startDateTime) && now.isBefore(endDateTime)) {
      // 当前时间在开始日期之后，结束日期之前，设置为进行中
      rehabilitationPlan.setStatus(1);
    } else {
      // 当前时间在结束日期之后，设置为已完成
      rehabilitationPlan.setStatus(2);
    }

    // 设置创建和更新时间
    rehabilitationPlan.setCreatedAt(now);
    rehabilitationPlan.setUpdatedAt(now);

    // 保存到数据库
    boolean result = this.save(rehabilitationPlan);
    if (!result) {
      throw new BusinessException(ErrorCode.SYSTEM_ERROR, "添加康复计划失败");
    }

    // 如果关联了伤病报告，更新伤病报告状态为"已解决"
    if (injuryReport != null) {
      injuryReport.setStatus("已解决");
      injuryReport.setUpdatedAt(now);
      injuryReportMapper.updateById(injuryReport);

      // 查找并更新相关的线上评估预约
      QueryWrapper<OnlineAssessmentAppointment> onlineQueryWrapper = new QueryWrapper<>();
      onlineQueryWrapper.eq("report_id", injuryReportId);
      List<OnlineAssessmentAppointment> onlineAppointments = onlineAssessmentAppointmentMapper
          .selectList(onlineQueryWrapper);
      for (OnlineAssessmentAppointment appointment : onlineAppointments) {
        appointment.setStatus("已完成");
        appointment.setUpdatedAt(now);
        onlineAssessmentAppointmentMapper.updateById(appointment);
      }

      // 查找并更新相关的线下评估预约
      QueryWrapper<OfflineAssessmentAppointment> offlineQueryWrapper = new QueryWrapper<>();
      offlineQueryWrapper.eq("report_id", injuryReportId);
      List<OfflineAssessmentAppointment> offlineAppointments = offlineAssessmentAppointmentMapper
          .selectList(offlineQueryWrapper);
      for (OfflineAssessmentAppointment appointment : offlineAppointments) {
        appointment.setStatus("已完成");
        appointment.setUpdatedAt(now);
        offlineAssessmentAppointmentMapper.updateById(appointment);
      }
    }

    return rehabilitationPlan.getId();
  }

  @Override
  public Boolean updateRehabilitationPlan(RehabilitationPlanUpdateRequest rehabilitationPlanUpdateRequest,
      Integer therapistId) {
    if (rehabilitationPlanUpdateRequest == null || rehabilitationPlanUpdateRequest.getId() == null) {
      throw new BusinessException(ErrorCode.PARAMS_ERROR);
    }

    // 检查康复计划是否存在
    Integer planId = rehabilitationPlanUpdateRequest.getId();
    RehabilitationPlan plan = this.getById(planId);
    if (plan == null) {
      throw new BusinessException(ErrorCode.NOT_FOUND_ERROR, "康复计划不存在");
    }

    // 检查是否是该理疗师创建的计划
    if (!plan.getTherapistId().equals(therapistId)) {
      throw new BusinessException(ErrorCode.NO_AUTH_ERROR, "无权修改该康复计划");
    }

    // 更新康复计划
    RehabilitationPlan updatePlan = new RehabilitationPlan();
    BeanUtil.copyProperties(rehabilitationPlanUpdateRequest, updatePlan);

    // 根据开始日期和结束日期自动设置status状态
    if (rehabilitationPlanUpdateRequest.getStartDate() != null
        && rehabilitationPlanUpdateRequest.getEndDate() != null) {
      LocalDateTime now = LocalDateTime.now();
      LocalDateTime startDateTime = rehabilitationPlanUpdateRequest.getStartDate().atStartOfDay();
      LocalDateTime endDateTime = rehabilitationPlanUpdateRequest.getEndDate().atTime(23, 59, 59);

      if (now.isBefore(startDateTime)) {
        // 当前时间在开始日期之前，设置为草稿状态
        updatePlan.setStatus(0);
      } else if (now.isAfter(startDateTime) && now.isBefore(endDateTime)) {
        // 当前时间在开始日期之后，结束日期之前，设置为进行中
        updatePlan.setStatus(1);
      } else {
        // 当前时间在结束日期之后，设置为已完成
        updatePlan.setStatus(2);
      }
    }

    // 更新时间
    updatePlan.setUpdatedAt(LocalDateTime.now());

    return this.updateById(updatePlan);
  }

  @Override
  public Boolean updateProgress(RehabilitationPlanProgressUpdateRequest progressUpdateRequest, Integer userId) {
    if (progressUpdateRequest == null || progressUpdateRequest.getId() == null) {
      throw new BusinessException(ErrorCode.PARAMS_ERROR);
    }

    // 检查康复计划是否存在
    Integer planId = progressUpdateRequest.getId();
    RehabilitationPlan plan = this.getById(planId);
    if (plan == null) {
      throw new BusinessException(ErrorCode.NOT_FOUND_ERROR, "康复计划不存在");
    }

    // 检查是否是相关用户(理疗师或患者)
    if (!plan.getTherapistId().equals(userId) && !plan.getPatientId().equals(userId)) {
      throw new BusinessException(ErrorCode.NO_AUTH_ERROR, "无权更新该康复计划进度");
    }

    // 更新进度
    RehabilitationPlan updatePlan = new RehabilitationPlan();
    updatePlan.setId(planId);
    updatePlan.setProgressStatus(progressUpdateRequest.getProgressStatus());
    updatePlan.setProgressNotes(progressUpdateRequest.getProgressNotes());

    // 患者才能更新学生反馈
    if (plan.getPatientId().equals(userId)) {
      updatePlan.setStudentFeedback(progressUpdateRequest.getStudentFeedback());
    }

    // 更新时间
    updatePlan.setUpdatedAt(LocalDateTime.now());

    return this.updateById(updatePlan);
  }

  @Override
  public RehabilitationPlanDetailVO getRehabilitationPlanDetailById(Integer id) {
    if (id == null) {
      throw new BusinessException(ErrorCode.PARAMS_ERROR);
    }

    // 查询康复计划
    RehabilitationPlan plan = this.getById(id);
    if (plan == null) {
      throw new BusinessException(ErrorCode.NOT_FOUND_ERROR, "康复计划不存在");
    }

    // 转换为VO
    RehabilitationPlanDetailVO detailVO = new RehabilitationPlanDetailVO();
    BeanUtil.copyProperties(plan, detailVO);

    // 添加状态名称
    detailVO.setStatusName(STATUS_MAP.getOrDefault(plan.getStatus(), "未知"));
    detailVO.setProgressStatusName(PROGRESS_STATUS_MAP.getOrDefault(plan.getProgressStatus(), "未知"));

    // 查询患者和理疗师信息
    User patient = userMapper.selectById(plan.getPatientId());
    User therapist = userMapper.selectById(plan.getTherapistId());

    if (patient != null) {
      detailVO.setPatientName(patient.getUsername());
    }

    if (therapist != null) {
      detailVO.setTherapistName(therapist.getUsername());
    }

    return detailVO;
  }

  @Override
  public Page<RehabilitationPlanVO> getRehabilitationPlanListByTherapist(Integer therapistId, Integer page,
      Integer pageSize, String keyword, Integer status) {
    if (therapistId == null || page == null || pageSize == null) {
      throw new BusinessException(ErrorCode.PARAMS_ERROR);
    }

    // 查询条件
    QueryWrapper<RehabilitationPlan> queryWrapper = new QueryWrapper<>();
    queryWrapper.eq("therapist_id", therapistId);

    // 关键词搜索
    if (keyword != null && !keyword.isEmpty()) {
      queryWrapper.like("title", keyword);
    }

    // 状态筛选
    if (status != null) {
      queryWrapper.eq("status", status);
    }

    // 按更新时间降序排序
    queryWrapper.orderByDesc("updated_at");

    // 分页查询
    Page<RehabilitationPlan> planPage = this.page(new Page<>(page, pageSize), queryWrapper);

    // 转换为VO列表
    Page<RehabilitationPlanVO> voPage = new Page<>();
    BeanUtil.copyProperties(planPage, voPage, "records");

    List<RehabilitationPlanVO> voList = planPage.getRecords().stream().map(plan -> {
      RehabilitationPlanVO vo = new RehabilitationPlanVO();
      BeanUtil.copyProperties(plan, vo);

      // 添加状态名称
      vo.setStatusName(STATUS_MAP.getOrDefault(plan.getStatus(), "未知"));
      vo.setProgressStatusName(PROGRESS_STATUS_MAP.getOrDefault(plan.getProgressStatus(), "未知"));

      // 查询患者信息
      User patient = userMapper.selectById(plan.getPatientId());
      if (patient != null) {
        vo.setPatientName(patient.getUsername());
      }

      // 理疗师名称
      User therapist = userMapper.selectById(therapistId);
      if (therapist != null) {
        vo.setTherapistName(therapist.getUsername());
      }

      return vo;
    }).collect(Collectors.toList());

    voPage.setRecords(voList);

    return voPage;
  }

  @Override
  public Page<RehabilitationPlanVO> getRehabilitationPlanListByPatient(Integer patientId, Integer page,
      Integer pageSize, String keyword, Integer status) {
    if (patientId == null || page == null || pageSize == null) {
      throw new BusinessException(ErrorCode.PARAMS_ERROR);
    }

    // 查询条件
    QueryWrapper<RehabilitationPlan> queryWrapper = new QueryWrapper<>();
    queryWrapper.eq("patient_id", patientId);

    // 关键词搜索
    if (keyword != null && !keyword.isEmpty()) {
      queryWrapper.like("title", keyword);
    }

    // 状态筛选
    if (status != null) {
      queryWrapper.eq("status", status);
    }

    // 按更新时间降序排序
    queryWrapper.orderByDesc("updated_at");

    // 分页查询
    Page<RehabilitationPlan> planPage = this.page(new Page<>(page, pageSize), queryWrapper);

    // 转换为VO列表
    Page<RehabilitationPlanVO> voPage = new Page<>();
    BeanUtil.copyProperties(planPage, voPage, "records");

    List<RehabilitationPlanVO> voList = planPage.getRecords().stream().map(plan -> {
      RehabilitationPlanVO vo = new RehabilitationPlanVO();
      BeanUtil.copyProperties(plan, vo);

      // 添加状态名称
      vo.setStatusName(STATUS_MAP.getOrDefault(plan.getStatus(), "未知"));
      vo.setProgressStatusName(PROGRESS_STATUS_MAP.getOrDefault(plan.getProgressStatus(), "未知"));

      // 患者名称
      User patient = userMapper.selectById(patientId);
      if (patient != null) {
        vo.setPatientName(patient.getUsername());
      }

      // 查询理疗师信息
      User therapist = userMapper.selectById(plan.getTherapistId());
      if (therapist != null) {
        vo.setTherapistName(therapist.getUsername());
      }

      return vo;
    }).collect(Collectors.toList());

    voPage.setRecords(voList);

    return voPage;
  }

  @Override
  public List<RehabilitationPlanVO> getRehabilitationPlansByInjuryReportId(Integer injuryReportId) {
    if (injuryReportId == null) {
      throw new BusinessException(ErrorCode.PARAMS_ERROR);
    }

    // 查询条件
    QueryWrapper<RehabilitationPlan> queryWrapper = new QueryWrapper<>();
    queryWrapper.eq("injury_report_id", injuryReportId);
    queryWrapper.orderByDesc("updated_at");

    List<RehabilitationPlan> plans = this.list(queryWrapper);

    // 转换为VO列表
    return plans.stream().map(plan -> {
      RehabilitationPlanVO vo = new RehabilitationPlanVO();
      BeanUtil.copyProperties(plan, vo);

      // 添加状态名称
      vo.setStatusName(STATUS_MAP.getOrDefault(plan.getStatus(), "未知"));
      vo.setProgressStatusName(PROGRESS_STATUS_MAP.getOrDefault(plan.getProgressStatus(), "未知"));

      // 查询患者信息
      User patient = userMapper.selectById(plan.getPatientId());
      if (patient != null) {
        vo.setPatientName(patient.getUsername());
      }

      // 查询理疗师信息
      User therapist = userMapper.selectById(plan.getTherapistId());
      if (therapist != null) {
        vo.setTherapistName(therapist.getUsername());
      }

      return vo;
    }).collect(Collectors.toList());
  }

  /**
   * 定时任务：每天凌晨2点自动更新所有康复计划的状态
   */
  @Scheduled(cron = "0 0 2 * * ?")
  public void updateAllPlanStatus() {
    log.info("开始执行康复计划状态自动更新任务");

    // 查询所有未取消的康复计划
    QueryWrapper<RehabilitationPlan> queryWrapper = new QueryWrapper<>();
    queryWrapper.ne("status", 3); // 排除已取消的计划
    List<RehabilitationPlan> plans = this.list(queryWrapper);

    int updatedCount = 0;
    LocalDateTime now = LocalDateTime.now();

    for (RehabilitationPlan plan : plans) {
      boolean needUpdate = false;
      Integer currentStatus = plan.getStatus();

      // 获取计划的开始和结束日期
      LocalDate startDate = plan.getStartDate();
      LocalDate endDate = plan.getEndDate();

      if (startDate != null && endDate != null) {
        LocalDateTime startDateTime = startDate.atStartOfDay();
        LocalDateTime endDateTime = endDate.atTime(23, 59, 59);

        // 判断状态是否需要更新
        if (currentStatus == 0 && now.isAfter(startDateTime)) {
          // 草稿状态 -> 进行中状态
          plan.setStatus(1);
          needUpdate = true;
        } else if (currentStatus == 1 && now.isAfter(endDateTime)) {
          // 进行中状态 -> 已完成状态
          plan.setStatus(2);
          needUpdate = true;
        }

        if (needUpdate) {
          plan.setUpdatedAt(now);
          this.updateById(plan);
          updatedCount++;
        }
      }
    }

    log.info("康复计划状态自动更新任务执行完成，共更新{}个计划", updatedCount);
  }
}